-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Document Export Functionality #238
Conversation
WalkthroughThe recent changes introduce a comprehensive document export functionality to the CodePair platform, enabling users to save Markdown documents as PDF, HTML, and Markdown files. This update enhances the user interface with a new download menu for seamless file exports, while adding supporting hooks and utilities for managing exports effectively. Overall, these enhancements significantly improve user experience and collaboration flexibility. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant DocumentHeader
participant DownloadMenu
participant useFileExport
participant FilesController
User->>DocumentHeader: Clicks save icon
DocumentHeader->>DownloadMenu: Opens download options
DownloadMenu->>User: Displays formats (PDF, HTML, Markdown)
User->>DownloadMenu: Selects format
DownloadMenu->>useFileExport: Triggers export function
useFileExport->>FilesController: Requests file export
FilesController->>User: Initiates file download
Assessment against linked issues
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (1)
frontend/package-lock.json
is excluded by!**/package-lock.json
Files selected for processing (10)
- frontend/package.json (2 hunks)
- frontend/src/components/cards/DocumentCard.tsx (2 hunks)
- frontend/src/components/common/DownloadMenu.tsx (1 hunks)
- frontend/src/components/editor/Preview.tsx (3 hunks)
- frontend/src/components/headers/DocumentHeader.tsx (3 hunks)
- frontend/src/contexts/PreviewRefContext.ts (1 hunks)
- frontend/src/hooks/useFileExport.ts (1 hunks)
- frontend/src/providers/PreviewRefProvider.tsx (1 hunks)
- frontend/src/routes.tsx (2 hunks)
- frontend/src/utils/localStorage.ts (1 hunks)
Files skipped from review due to trivial changes (1)
- frontend/src/utils/localStorage.ts
Additional comments not posted (42)
frontend/src/contexts/PreviewRefContext.ts (3)
1-2
: Good practice: Import statements.The import statements are clear and concise.
4-6
: Interface definition looks good.The
PreviewRefContextValue
interface is well-defined.
8-10
: Context initialization looks good.The
PreviewRefContext
is correctly initialized with a default value.frontend/src/providers/PreviewRefProvider.tsx (3)
1-3
: Good practice: Import statements.The import statements are clear and concise.
5-7
: Provider component definition looks good.The
PreviewRefProvider
component is well-defined and uses theuseRef
hook appropriately.
9-11
: Context provider implementation looks good.The
PreviewRefContext.Provider
is correctly implemented to pass down thepreviewRef
.frontend/src/components/cards/DocumentCard.tsx (3)
2-3
: Reordered import statements.The import statements are reordered for better organization.
6-6
: New import statement added.The import of
documentNameStorage
is correctly added.
18-18
: Functionality enhancement: Storing document title in local storage.The call to
documentNameStorage.setDocumentName(document.title);
enhances the functionality by storing the document's title in local storage.frontend/src/components/common/DownloadMenu.tsx (6)
1-4
: LGTM! Imports are relevant and necessary.The import statements are appropriate for the functionality described in the file.
6-15
: LGTM! State management and handlers are well-implemented.The state management and event handlers for opening and closing the menu are correctly implemented.
17-17
: LGTM! Custom hook usage is appropriate.The
useFileExport
hook is correctly used to handle file export functionality.
19-32
: LGTM! Export handlers are well-implemented.The export handlers use
useCallback
for performance optimization and correctly call the respective export functions.
34-52
: LGTM! JSX structure and accessibility considerations are well-implemented.The JSX structure is clear and follows Material-UI best practices. The
aria
attributes are correctly used for accessibility.
54-54
: LGTM! Export statement is correctly implemented.The
DownloadMenu
component is correctly exported as the default export.frontend/src/hooks/useFileExport.ts (7)
1-9
: LGTM! Imports are relevant and necessary.The import statements are appropriate for the functionality described in the file.
11-15
: LGTM! Interface definition is correct.The
useFileExportReturn
interface is correctly defined to ensure type safety for the hook's return values.
17-20
: LGTM! Hook initialization is correct.The
useFileExport
hook is correctly initialized and retrieves necessary data from the Redux store and context.
27-50
: LGTM!exportToPDF
function is well-implemented.The
exportToPDF
function usesjspdf-html2canvas
to convert HTML content to a PDF file and handles potential errors gracefully.
52-55
: LGTM!exportToTXT
function is well-implemented.The
exportToTXT
function creates a text file from the Markdown content and usesfile-saver
to save the file.
57-74
: LGTM!exportToDOCX
function is well-implemented.The
exportToDOCX
function creates a DOCX file from the Markdown content using thedocx
library and saves the file usingfile-saver
.
76-77
: LGTM! Return statement is correctly implemented.The
useFileExport
hook correctly returns the three export functions.frontend/src/routes.tsx (4)
1-14
: LGTM! Imports are relevant and necessary.The import statements are appropriate for the functionality described in the file.
63-67
: LGTM! Routing structure and enhancement are well-implemented.The routing structure is well-implemented. Wrapping the
DocumentLayout
component withPreviewRefProvider
is a logical enhancement for managing document previews.
Line range hint
96-126
:
LGTM!injectProtectedRoute
function is correctly implemented.The
injectProtectedRoute
function ensures that routes are protected based on their access type.
Line range hint
128-128
:
LGTM! Export statement is correctly implemented.The routes are correctly exported using the
injectProtectedRoute
function.frontend/package.json (4)
40-40
: Dependency Addition:docx
The
docx
library is added to handle DOCX file generation. Ensure it is necessary and used securely.
41-41
: Dependency Addition:file-saver
The
file-saver
library is added for saving files on the client side. Ensure it is necessary and used securely.
43-43
: Dependency Addition:jspdf-html2canvas
The
jspdf-html2canvas
library is added for PDF generation from HTML content. Ensure it is necessary and used securely.
74-74
: DevDependency Addition:@types/file-saver
The
@types/file-saver
type declaration is added to support TypeScript development. Ensure it is necessary and used correctly.frontend/src/components/editor/Preview.tsx (8)
2-2
: Import Addition:MarkdownPreview
The
MarkdownPreview
component is imported for rendering Markdown content. Ensure it is necessary and used correctly.
4-4
: Import Addition:katex
The
katex
library is imported for rendering LaTeX math in Markdown. Ensure it is necessary and used correctly.
5-5
: Import Addition:useContext
anduseEffect
The
useContext
anduseEffect
hooks are imported for managing context and side effects. Ensure they are necessary and used correctly.
11-11
: Import Addition:PreviewRefContext
The
PreviewRefContext
is imported to manage the preview reference context. Ensure it is necessary and used correctly.
15-15
: Import Addition:documentNameStorage
The
documentNameStorage
utility is imported for managing document names in local storage. Ensure it is necessary and used correctly.
23-23
: Context Usage:PreviewRefContext
The
previewRef
is obtained from thePreviewRefContext
. Ensure it is necessary and used correctly.
46-48
: useEffect Hook: Local Storage CleanupThe
useEffect
hook is added to clean up document names from local storage when the component unmounts. This prevents potential data retention issues.
59-59
: Prop Addition:ref
The
previewRef
is passed to theMarkdownPreview
component. Ensure it is necessary and used correctly.frontend/src/components/headers/DocumentHeader.tsx (4)
1-4
: Import Consolidation: MUI IconsThe MUI icons are consolidated into individual import statements for better clarity and organization.
18-18
: Import Addition:useDispatch
anduseSelector
The
useDispatch
anduseSelector
hooks are imported for managing Redux state. Ensure they are necessary and used correctly.
25-25
: Import Addition:DownloadMenu
The
DownloadMenu
component is imported for providing download options in the document header. Ensure it is necessary and used correctly.
129-129
: Component Addition:DownloadMenu
The
DownloadMenu
component is added to the document header to provide download options. Ensure it is necessary and used correctly.
NotifyThis is a problem I learned from the additional modification. |
frontend/src/utils/localStorage.ts
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is redundant data saving functions.
You can get this data in redux store.
(Refer to frontend/src/store/documentSlice.ts
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
const { exportToPDF, exportToTXT, exportToDOCX } = useFileExport(); | ||
|
||
const handleExportToPDF = useCallback(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems necessary to standardize either wrapping or not wrapping handlers in the Component with useCallback
.
While modifying to convert Markdown text to PDF, it is necessary to check if there is an option to render images. If it is determined to be impossible on the frontend, backend code modifications are possible. However, the first option to consider should be to make changes on the frontend alone, as this seems optimal. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
Outside diff range, codebase verification and nitpick comments (2)
backend/src/files/types/export-file.type.ts (1)
3-5
: Enhance property descriptions and consider extending export types.The descriptions in the
@ApiProperty
decorators could be more descriptive to provide better API documentation. Additionally, consider if other export types (e.g., DOCX, TXT) should be supported.- @ApiProperty({ type: String, description: "export_type" }) + @ApiProperty({ type: String, description: "The format to export the file (e.g., pdf, html, markdown)" })frontend/src/hooks/useFileExport.ts (1)
31-33
: Internationalize snackbar messages.The
enqueueSnackbar
messages should be internationalized for better localization support.- enqueueSnackbar(`${exportType.toUpperCase()} 파일 내보내기 시작...`, { + enqueueSnackbar(t(`${exportType.toUpperCase()} file export started...`), { - enqueueSnackbar(`${exportType.toUpperCase()} 파일이 성공적으로 내보내졌습니다.`, { + enqueueSnackbar(t(`${exportType.toUpperCase()} file exported successfully.`), { - enqueueSnackbar(`${exportType.toUpperCase()} 파일 내보내기에 실패했습니다.`, { + enqueueSnackbar(t(`${exportType.toUpperCase()} file export failed.`), {Also applies to: 66-68, 71-73
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (1)
backend/package-lock.json
is excluded by!**/package-lock.json
Files selected for processing (9)
- backend/package.json (1 hunks)
- backend/src/files/files.controller.ts (3 hunks)
- backend/src/files/files.service.ts (2 hunks)
- backend/src/files/types/export-file.type.ts (1 hunks)
- frontend/src/components/cards/DocumentCard.tsx (1 hunks)
- frontend/src/components/common/DownloadMenu.tsx (1 hunks)
- frontend/src/components/editor/Preview.tsx (1 hunks)
- frontend/src/hooks/useFileExport.ts (1 hunks)
- frontend/src/routes.tsx (1 hunks)
Files skipped from review due to trivial changes (2)
- frontend/src/components/cards/DocumentCard.tsx
- frontend/src/routes.tsx
Files skipped from review as they are similar to previous changes (2)
- frontend/src/components/common/DownloadMenu.tsx
- frontend/src/components/editor/Preview.tsx
Additional context used
Biome
frontend/src/hooks/useFileExport.ts
[error] 8-12: The enum declaration should not be const
Const enums are not supported by bundlers and are incompatible with the 'isolatedModules' mode. Their use can lead to import inexistent values.
See TypeScript Docs for more details.
Safe fix: Turn the const enum into a regular enum.(lint/suspicious/noConstEnum)
[error] 52-53: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
Additional comments not posted (6)
backend/src/files/types/export-file.type.ts (1)
14-17
: LGTM!The interface
ExportFileResponseDto
is well-defined and straightforward.backend/src/files/files.controller.ts (1)
45-46
: LGTM!The correction in the description improves clarity in the API documentation.
backend/package.json (3)
38-38
: LGTM!The addition of
fs-extra
is appropriate for handling file system operations more efficiently.
39-39
: LGTM!The addition of
html-pdf-node
is appropriate for generating PDF files from HTML content.
41-41
: LGTM!The addition of
markdown-it
is appropriate for processing markdown content.backend/src/files/files.service.ts (1)
1-18
: LGTM!The imports and constructor initialization are appropriate.
Also applies to: 23-26
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (1)
- frontend/src/components/headers/DocumentHeader.tsx (3 hunks)
Files skipped from review as they are similar to previous changes (1)
- frontend/src/components/headers/DocumentHeader.tsx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (1)
- backend/src/files/files.controller.ts (3 hunks)
Additional context used
Biome
backend/src/files/files.controller.ts
[error] 75-75: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
Additional comments not posted (3)
backend/src/files/files.controller.ts (3)
1-16
: Imports look good.The new imports are necessary for the added export functionality.
45-45
: Documentation correction approved.The correction from "Create rresigned URL for download" to "Create Presigned URL for download" improves clarity.
56-77
: Function implementation approved.The
exportMarkdown
function is correctly implemented and follows best practices.Tools
Biome
[error] 75-75: The catch clause that only rethrows the original error is redundant.
These unnecessary catch clauses can be confusing. It is recommended to remove them.
(lint/complexity/noUselessCatch)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (8)
- backend/package.json (1 hunks)
- backend/src/files/files.controller.ts (3 hunks)
- backend/src/files/files.service.ts (2 hunks)
- backend/src/files/types/export-file.type.ts (1 hunks)
- frontend/src/components/common/DownloadMenu.tsx (1 hunks)
- frontend/src/hooks/api/file.ts (2 hunks)
- frontend/src/hooks/api/types/file.d.ts (1 hunks)
- frontend/src/hooks/useFileExport.ts (1 hunks)
Files skipped from review as they are similar to previous changes (4)
- backend/package.json
- backend/src/files/files.service.ts
- backend/src/files/types/export-file.type.ts
- frontend/src/components/common/DownloadMenu.tsx
Additional context used
Biome
frontend/src/hooks/useFileExport.ts
[error] 8-12: The enum declaration should not be const
Const enums are not supported by bundlers and are incompatible with the 'isolatedModules' mode. Their use can lead to import inexistent values.
See TypeScript Docs for more details.
Safe fix: Turn the const enum into a regular enum.(lint/suspicious/noConstEnum)
[error] 46-46: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
Additional comments not posted (6)
frontend/src/hooks/api/types/file.d.ts (1)
17-21
: Ensure consistency in property naming.The class
ExportFileRequest
is well-defined, but ensure that the property names are consistent with any existing naming conventions in the project.frontend/src/hooks/api/file.ts (1)
3-8
: LGTM! Ensure the import is necessary.The import statement for
ExportFileRequest
is correct. Ensure that it is necessary and used appropriately in the file.frontend/src/hooks/useFileExport.ts (4)
1-6
: Imports look good.The imported modules and functions are necessary for the functionality of the hook.
14-20
: Type and interface declarations look good.The type alias and interface improve type safety and readability.
73-75
: Export functions look good.The functions correctly call
handleExportFile
with the appropriate file extension.
77-78
: Return statement looks good.The return statement correctly provides the export functions to the caller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (1)
- frontend/src/components/common/DownloadMenu.tsx (1 hunks)
Files skipped from review as they are similar to previous changes (1)
- frontend/src/components/common/DownloadMenu.tsx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files ignored due to path filters (1)
backend/package-lock.json
is excluded by!**/package-lock.json
Files selected for processing (1)
- frontend/src/hooks/useFileExport.ts (1 hunks)
Additional context used
Biome
frontend/src/hooks/useFileExport.ts
[error] 8-12: The enum declaration should not be const
Const enums are not supported by bundlers and are incompatible with the 'isolatedModules' mode. Their use can lead to import inexistent values.
See TypeScript Docs for more details.
Safe fix: Turn the const enum into a regular enum.(lint/suspicious/noConstEnum)
Additional comments not posted (5)
frontend/src/hooks/useFileExport.ts (5)
1-6
: Imports look good.The import statements are necessary and correctly used in the file.
23-27
: Hooks usage looks good.The hooks are used correctly and the dependency arrays are accurate.
29-70
: Functionality looks good, but ensureuseCallback
dependency array includeseditorStore
anddocumentStore
.The
handleExportFile
function is well-implemented, handling errors and optimizing performance. However, ensure that theuseCallback
dependency array includeseditorStore
anddocumentStore
to use the latest state.
44-46
: Simplifycontent-disposition
header parsing using optional chaining.Use optional chaining to simplify the
content-disposition
header parsing.
72-77
: Return statement looks good.The return statement correctly includes the export functions for PDF, HTML, and Markdown.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your contribution.
@minai621 |
What this PR does / why we need it:
This pull request introduces a new document export feature for CodePair. Currently, users can write Markdown documents in CodePair, but there was no functionality to export these documents into various file formats. With this update, users can now export their Markdown documents as PDF, TXT, and DOCX files.
Which issue(s) this PR fixes:
Fixes #191
Special notes for your reviewer:
The implementation uses local storage to save the document title for file naming purposes. I would appreciate your feedback on whether there are better alternatives for this approach.
Does this PR introduce a user-facing change?:
Additional documentation:
Checklist:
Summary by CodeRabbit
New Features
DownloadMenu
component for exporting files in PDF, HTML, and Markdown formats.DownloadMenu
component into theDocumentHeader
for easier access to download options.Improvements
FilesService
to support versatile content export capabilities (PDF, HTML, Markdown).